package com.want.controller;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import com.want.api.blog.BlogApi;
import com.want.api.user.UserApi;
import com.want.model.dto.Result;
import com.want.model.dto.ResultUtil;
import com.want.req.base.PageReqDto;
import com.want.req.blog.dto.CreateBlogDto;
import com.want.req.blog.dto.ListBlogReqDto;
import com.want.req.blog.dto.PoolBlogDto;
import com.want.req.blog.dto.UpdateBlogDto;
import com.want.req.user.dto.LoginReqDto;
import com.want.resp.base.PageResp;
import com.want.resp.blog.dto.BlogDetailDto;
import com.want.resp.blog.dto.BlogDto;
import com.want.resp.blog.dto.BlogTagDto;
import com.want.resp.blog.dto.BlogTypeDto;
import com.want.resp.user.dto.LoginRespDto;
import com.want.resp.user.dto.UserDto;
import com.want.resp.user.dto.UserInfoDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.repository.query.Param;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author WangZhiJian
 * @since 2021/12/7 0007
 */
@Slf4j
@RestController
@RequestMapping("front")
public class FrontController {
    @Resource
    private BlogApi blogApi;
    @Resource
    private UserApi userApi;

    @PostMapping(value = "listBlog") //,produces = MediaType.TEXT_EVENT_STREAM_VALUE
    public Mono<Result<PageResp<BlogDto>>> listBlog(@RequestBody PageReqDto<ListBlogReqDto> pageReqDto){
        return blogApi.listBlog(pageReqDto);
    }
    @GetMapping("blog")
    public Mono<Result<BlogDetailDto>> blog(Integer id){
        return blogApi.blog(id)
                .flatMap(result ->{
                    if(Objects.equals(result.getCode(),200)){
                        Mono<Result<UserDto>> userMono = Optional.ofNullable(result.getData())
                                .map(BlogDto::getUserId)
                                .map(userApi::findById)
                                .orElseGet(Mono::empty);
                        return userMono
                                .map(uResult -> Result.<BlogDetailDto>builder()
                                        .code(uResult.getCode())
                                        .msg(uResult.getMsg())
                                        .data(BlogDetailDto.builder()
                                                .userDto(uResult.getData())
                                                .blogDto(result.getData())
                                                .build()
                                        ).build());
                    }
                    return Mono.defer(() -> Mono.just(Result.<BlogDetailDto>builder().code(result.getCode())
                            .msg(result.getMsg())
                            .build()));
                });
    }

    @GetMapping("online/{status}")
    @SaCheckRole(value = "admin")
    public Mono<Result<Integer>> online(@Param("id") Integer id, @PathVariable("status") Integer status){
        UpdateBlogDto updateBlogDto = UpdateBlogDto.builder().id(id).online(status).build();
        return blogApi.updateBlog(updateBlogDto);

    }

    @GetMapping("blogShouldAuth")
    @SaCheckRole(value = "admin")
    public Mono<Result<BlogDetailDto>> blogShouldAuth(Integer id){
        return this.blog(id);
    }

    @PostMapping("blog/add")
    @SaCheckRole(value = "admin")
    public Mono<Result<Integer>> addBlog(@RequestBody CreateBlogDto createBlogDto){
        createBlogDto.setUserId(StpUtil.getLoginIdAsInt());
        return blogApi.createBlog(createBlogDto);
    }

    @PostMapping("blog/update")
    @SaCheckRole(value = "admin")
    public Mono<Result<Integer>> updateBlog(@RequestBody UpdateBlogDto updateBlogDto){
        return blogApi.updateBlog(updateBlogDto);
    }

    @PostMapping("blog/delete")
    @SaCheckRole(value = "admin")
    public Mono<Result<Integer>> deleteBlog(@RequestBody @NotEmpty @NotNull List<Integer> idList){
        return blogApi.delete(idList);
    }

    @GetMapping("blog/getContent/{id}")
    public Mono<Result<String>> getContent(@PathVariable("id") Integer id){
        return blogApi.getContent(id);
    }

    @GetMapping("goodBlog")
    public Mono<Result<Integer>> updateBlog(Integer id){
        PoolBlogDto poolBlogDto = new PoolBlogDto();
        poolBlogDto.setBlogId(id);
        return blogApi.goodBlog(poolBlogDto);
    }

    @GetMapping(value = "listAllBlogType")
    public Mono<Result<PageResp<BlogTypeDto>>> listAllBlogType(){
        return blogApi.listAllBlogType();
    }

    @GetMapping(value = "listAllBlogTag")
    public Mono<Result<PageResp<BlogTagDto>>> listAllBlogTag(){
        return blogApi.listAllBlogTag();
    }

    @PostMapping("login")
    public Mono<Result<LoginRespDto>> login(@RequestBody @Validated LoginReqDto loginReqDto){
        return userApi.login(loginReqDto)
                .doOnNext(resp -> Mono.just(resp)
                        .filter(Result::success)
                        .map(Result::getData)
                        .subscribe(data -> {
                            StpUtil.login(data.getId());
                            data.setToken(StpUtil.getTokenValue());
                        }));
    }

    @GetMapping("userInfo")
    public Mono<Result<UserInfoDto>> userInfo(){
        return userApi.userInfo(Integer.valueOf((String) StpUtil.getLoginId()));
    }
    @GetMapping("getMenu")
    public Mono<Result<List<String>>> getMenu(){
        return Mono.just(new ArrayList<String>()).map(ResultUtil::ofSuccess);
    }

}
